//
//  String+Encrypt.swift
//  cmCOM
//
//  Created by Toj on 5/31/22.
//
//  摘要/ 加密 等算法
//

import Foundation
import CommonCrypto

// MARK: - CMHmac 摘要类型
public enum CMHmac {
    case MD5
    case SHA256

    var toHmacAlg: CCHmacAlgorithm {
        var result: Int = 0
        switch self {
        case .MD5:
            result = kCCHmacAlgMD5
        case .SHA256:
            result = kCCHmacAlgSHA256
        }
        return CCHmacAlgorithm(result)
    }

    var length: Int {
        var result: CInt = 0
        switch self {
        case .MD5:
            result = CC_MD5_DIGEST_LENGTH
        case .SHA256:
            result = CC_SHA256_DIGEST_LENGTH
        }
        return Int(result)
    }
}

// MARK: - CCHmac 摘要方式
public extension String {
    
    private func cm_hmac_digest(algorithm: CMHmac, key: String) -> [UInt8]? {
        guard let cData = cString(using: .utf8),
              let cKey = key.cString(using: .utf8)
        else { return nil }
        
        var digest = [UInt8](repeating: 0, count: algorithm.length)
        CCHmac(algorithm.toHmacAlg, cKey, strlen(cKey), cData, strlen(cData), &digest)
        
        return digest
    }
    
    func cm_hmac(algorithm: CMHmac, key: String) -> Self {
        guard let digest = cm_hmac_digest(algorithm: algorithm, key: key)
        else { return "" }
        
        let result = digest.reduce("") { $0 + String(format:"%02x", $1) }
        print(#function + " -> result: \(result)")
        
        return result
    }
    
    func cm_hmacBase64(algorithm: CMHmac, key: String) -> Self {
        
        guard let digest = cm_hmac_digest(algorithm: algorithm, key: key)
        else { return "" }
        
        let hmacData = NSData(bytes: digest, length: Int(algorithm.length))
        let result = hmacData.base64EncodedString()
        print(#function + " -> result: \(result)")
        
        return result
    }
}

// MARK: - MD5 摘要方式
public extension String {
    
    var cm_md5: Self {
        guard let cData = cString(using: .utf8) else { return "" }
        
        var digest = [UInt8](repeating: 0, count: Int(CC_MD5_DIGEST_LENGTH))
        CC_MD5(cData, CC_LONG(cData.count - 1), &digest)
        
        return digest.reduce("") { $0 + String(format:"%02x", $1) }
    }
}

// MARK: - SHA 摘要方式
public extension String {
    
    var cm_sha1: Self {
        guard let cData = cString(using: .utf8) else { return "" }
        
        var digest = [UInt8](repeating: 0, count: Int(CC_SHA1_DIGEST_LENGTH))
        CC_SHA1(cData, CC_LONG(cData.count - 1), &digest)
        
        return digest.reduce("") { $0 + String(format:"%02x", $1) }
    }
    
    var cm_sha224: Self {
        guard let cData = cString(using: .utf8) else { return "" }
        
        var digest = [UInt8](repeating: 0, count: Int(CC_SHA224_DIGEST_LENGTH))
        CC_SHA224(cData, CC_LONG(cData.count - 1), &digest)
        
        return digest.reduce("") { $0 + String(format:"%02x", $1) }
    }
    
    var cm_sha256: Self {
        guard let cData = cString(using: .utf8) else { return "" }
        
        var digest = [UInt8](repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH))
        CC_SHA256(cData, CC_LONG(cData.count - 1), &digest)
        
        return digest.reduce("") { $0 + String(format:"%02x", $1) }
    }
    
    var cm_sha384: Self {
        guard let cData = cString(using: .utf8) else { return "" }
        
        var digest = [UInt8](repeating: 0, count: Int(CC_SHA384_DIGEST_LENGTH))
        CC_SHA384(cData, CC_LONG(cData.count - 1), &digest)
        
        return digest.reduce("") { $0 + String(format:"%02x", $1) }
    }
    
    var cm_sha521: Self {
        guard let cData = cString(using: .utf8) else { return "" }
   
        var digest = [UInt8](repeating: 0, count: Int(CC_SHA512_DIGEST_LENGTH))
        CC_SHA512(cData, CC_LONG(cData.count - 1), &digest)

        return digest.reduce("") { $0 + String(format:"%02x", $1) }
    }
}


// MARK: AES
/**
 * 高级加密标准(英语：Advanced Encryption Standard, 缩写: AES)
 * 又称Rijndael加密法(荷兰语发音: [ˈrɛindaːl], 音似英文的"Rhine doll")
 * 这个标准用来替代原先的DES, 已经被多方分析且广为全世界所使用.
 */
public extension String {
    
   // CryptoSwift
}
